#include "window.h"
#include <vector>
#include <iostream>

#include <QKeySequence>
#include "objectTreeItem.h"
#include "polygonDialog.h"
#include "cuboidDialog.h"
#include "sphereDialog.h"
#include "cylinderDialog.h"
#include "coneDialog.h"
#include "panel.h"
#include "analysisDialog.h"
#include "scaleDialog.h"
#include "rotateDialog.h"
#include "translateDialog.h"
#include "sweepDialog.h"
#include "input.h"
#include "faceTreeItem.h"
#include "edgeTreeItem.h"
#include "vertexTreeItem.h"

Window::Window(){
	setWindowTitle(QString::fromUtf8("[MODELAGEM GEOMÉTRICA] Brep"));
    statusBar()->showMessage(tr(""));
    setUnifiedTitleAndToolBarOnMac(true);

	canvas = new GLWidget(this);
	setCentralWidget(canvas);

	tree = NULL;

    inOperation = false;

	createWindow();
}

Window::~Window(){
	if(canvas) delete canvas;
}

void Window::changeShowFace(bool _b){
    if(!_b){
        if(!canvas->isShowingEdge() && !canvas->isShowingVertex())
        {
            newShowFaceAct->setChecked(true);
            return;
        }
    }
    canvas->changeShowFace(_b);
}

void Window::changeShowEdge(bool _b){
    if(!_b){
        if(!canvas->isShowingFace() && !canvas->isShowingVertex())
        {
            newShowEdgeAct->setChecked(true);
            return;
        }
    }
    canvas->changeShowEdge(_b);
}

void Window::changeShowVertex(bool _b){
    if(!_b){
        if(!canvas->isShowingEdge() && !canvas->isShowingFace())
        {
            newShowVertexAct->setChecked(true);
            return;
        }
    }
    canvas->changeShowVertex(_b);
}


void Window::translateOperation(){
    TranslateDialog *dlg = new TranslateDialog(previousSelected, this);
    dlg->show();
    connect(dlg, SIGNAL(done()), canvas, SLOT(updateGL()));

    updateActions();
}

void Window::rotateOperation(){
    RotateDialog *dlg = new RotateDialog(previousSelected, this);
    dlg->show();
    connect(dlg, SIGNAL(done()), canvas, SLOT(updateGL()));

    updateActions();
}

void Window::scaleOperation(){
    ScaleDialog *dlg = new ScaleDialog(previousSelected, this);
    dlg->show();
    connect(dlg, SIGNAL(done()), canvas, SLOT(updateGL()));

    updateActions();
}

void Window::sweepOperation(){
    SweepDialog *dlg = new SweepDialog(previousSelected, this);
    dlg->show();
    connect(dlg, SIGNAL(done()), canvas, SLOT(updateGL()));

    QTreeWidgetItem *item = previousSelected.front();
    switch( ((TreeItem *)item)->getType() )
    {
        case DEFAULT:
            connect(dlg, SIGNAL(done()), ((ObjectTreeItem *)item->parent()), SLOT(update()));
            break;
        case FACE:
            connect(dlg, SIGNAL(done()), ((ObjectTreeItem *)item->parent()->parent()), SLOT(update()));
            break;
    }


    updateActions();
}

void Window::holeOperation(){
    QTreeWidgetItem *item1 = previousSelected.front();
    QTreeWidgetItem *item2 = previousSelected.back();

    ObjectTreeItem *objectItem = (ObjectTreeItem *)(item1->parent()->parent());
    Object *obj = objectItem->getObject();
    obj->makeHole(((FaceTreeItem *)item1)->getFace(), ((FaceTreeItem *)item2)->getFace());

    objectItem->update();

    updateActions();
}

void Window::selectAdjacentFace(){
    inOperation = true;
    TreeItem * top = (TreeItem *)previousSelected.front();
    unsigned int type = top->getType();
    for(int i = 0; i < previousSelected.size(); i++)
    {
        QTreeWidgetItem *item = previousSelected[i];
        switch(type)
        {
            case FACE:
            {
                ((FaceTreeItem *)item)->getFace()->selectAdjacentFace();
                break;
            }
            case EDGE:
            {
                ((EdgeTreeItem *)item)->getEdge()->selectAdjacentFace();
                item->setSelected(false);
                break;
            }
            case VERTEX:
            {
                ((VertexTreeItem *)item)->getVertex()->selectAdjacentFace();
                item->setSelected(false);
                break;
            }
        }
    }

    ((ObjectTreeItem *)(((QTreeWidgetItem *)top)->parent()->parent()))->updateFaces();

    inOperation = false;
    changeSelection();
}

void Window::selectAdjacentEdge(){
    inOperation = true;
    TreeItem * top = (TreeItem *)previousSelected.front();
    unsigned int type = top->getType();
    for(int i = 0; i < previousSelected.size(); i++)
    {
        QTreeWidgetItem *item = previousSelected[i];
        switch(type)
        {
            case FACE:
            {
                ((FaceTreeItem *)item)->getFace()->selectAdjacentEdge();
                item->setSelected(false);
                break;
            }
            case EDGE:
            {
                ((EdgeTreeItem *)item)->getEdge()->selectAdjacentEdge();
                break;
            }
            case VERTEX:
            {
                ((VertexTreeItem *)item)->getVertex()->selectAdjacentEdge();
                item->setSelected(false);
                break;
            }
        }
    }

    ((ObjectTreeItem *)(((QTreeWidgetItem *)top)->parent()->parent()))->updateEdges();

    inOperation = false;
    changeSelection();
}

void Window::selectAdjacentVertex(){
    inOperation = true;
    TreeItem * top = (TreeItem *)previousSelected.front();
    unsigned int type = top->getType();
    for(int i = 0; i < previousSelected.size(); i++)
    {
        QTreeWidgetItem *item = previousSelected[i];
        switch(type)
        {
            case FACE:
            {
                ((FaceTreeItem *)item)->getFace()->selectAdjacentVertex();
                item->setSelected(false);
                break;
            }
            case EDGE:
            {
                ((EdgeTreeItem *)item)->getEdge()->selectAdjacentVertex();
                item->setSelected(false);
                break;
            }
            case VERTEX:
            {
                ((VertexTreeItem *)item)->getVertex()->selectAdjacentVertex();
                break;
            }
        }
    }

    ((ObjectTreeItem *)(((QTreeWidgetItem *)top)->parent()->parent()))->updateEdges();

    inOperation = false;
    changeSelection();
}

void Window::createWindow(){

    //Criando paineis ----------------------------------------------------------
    QDockWidget *treePanelDock = new QDockWidget(tr("Objetos"), this);

    tree = new QTreeWidget(treePanelDock);
    tree->setHeaderHidden(true);
    tree->setContextMenuPolicy(Qt::ActionsContextMenu);
    tree->setSelectionMode(QAbstractItemView::ExtendedSelection);
    tree->setSelectionBehavior(QAbstractItemView::SelectRows);
    tree->setAnimated(true);
    tree->setExpandsOnDoubleClick(false);

	treePanelDock->setWidget(tree);
    treePanelDock->setMaximumWidth(350);
//    treePanelDock->setMinimumHeight(200);
    addDockWidget(Qt::RightDockWidgetArea, treePanelDock);

    QTreeWidgetItem *headerItem = tree->headerItem();
    headerItem->setText(0, "Objetos");

    connect(tree, SIGNAL(itemSelectionChanged()), this, SLOT(changeSelection()));


//    QDockWidget *___PanelDock = new QDockWidget(tr("Painel"), this);
//
//    Panel *___Panel = new Panel(___PanelDock);
//
//	___PanelDock->setWidget(___Panel);
//    ___PanelDock->setMaximumWidth(300);
//
//    addDockWidget(Qt::RightDockWidgetArea, ___PanelDock);

//    connect(___Panel, SIGNAL(done()), this, SLOT(create___()));




    //Criando ações ------------------------------------------------------------
    QAction *newSceneAct = new QAction(QString::fromUtf8("Nova Cena"), this);
    newSceneAct->setShortcuts(QKeySequence::New);
    newSceneAct->setStatusTip(QString::fromUtf8("Criar uma nava cena sem objetos."));
    connect(newSceneAct, SIGNAL(triggered()), this, SLOT(newScene()));
    connect(newSceneAct, SIGNAL(triggered()), this, SLOT(updateActions()));

//    openSceneAct = new QAction(QString::fromUtf8("Abrir Cena"), this);
//    openSceneAct->setShortcuts(QKeySequence::Open);
//    openSceneAct->setStatusTip(QString::fromUtf8("Abrir uma nava cena."));
//    connect(openSceneAct, SIGNAL(triggered()), this, SLOT(openScene()));
//    connect(openSceneAct, SIGNAL(triggered()), this, SLOT(updateActions()));
//
//    openObjectAct = new QAction(QString::fromUtf8("Abrir Objeto"), this);
////    openObjectAct->setShortcuts();
//    openObjectAct->setStatusTip(QString::fromUtf8("Abrir um novo objeto na cena corrente."));
//    connect(openObjectAct, SIGNAL(triggered()), this, SLOT(openObject()));
//    connect(openObjectAct, SIGNAL(triggered()), this, SLOT(updateActions()));


    saveObjectsAct = new QAction(QString::fromUtf8("Salvar objetos"), this);
    saveObjectsAct->setShortcuts(QKeySequence::Save);
    saveObjectsAct->setStatusTip(QString::fromUtf8("Salvar objetos da cena atual."));
    saveObjectsAct->setEnabled(false);
    connect(saveObjectsAct, SIGNAL(triggered()), this, SLOT(saveSceneObjects()));

    QAction *saveObjectsAsAct = new QAction(QString::fromUtf8("Salvar objetos como..."), this);
    saveObjectsAsAct->setShortcuts(QKeySequence::SaveAs);
    saveObjectsAsAct->setStatusTip(QString::fromUtf8("Salvar objetos da cena atual em novo arquivo."));
    connect(saveObjectsAsAct, SIGNAL(triggered()), this, SLOT(saveSceneObjectsAs()));

    QAction *exitAct = new QAction(QString::fromUtf8("Sair"), this);
    exitAct->setShortcuts(QKeySequence::Quit);
    exitAct->setStatusTip(QString::fromUtf8("Sair da aplicação."));
    connect(exitAct, SIGNAL(triggered()), qApp, SLOT(closeAllWindows()));


    editObjectAct = new QAction(QString::fromUtf8("Modificar objeto"), this);
    editObjectAct->setStatusTip(QString::fromUtf8("Modifica os objetos selecionados"));
    editObjectAct->setDisabled(true);
//    connect(editObjectAct, SIGNAL(triggered()), this, SLOT(editObjectDialog()));
    connect(tree, SIGNAL(itemDoubleClicked(QTreeWidgetItem *, int)), this, SLOT(editObjectDialog(QTreeWidgetItem *, int)));

    deleteObjectAct = new QAction(QString::fromUtf8("Deletar objeto"), this);
    deleteObjectAct->setShortcuts(QKeySequence::Delete);
    deleteObjectAct->setEnabled(false);
    deleteObjectAct->setStatusTip(QString::fromUtf8("Deletar objetos selecionados."));
    connect(deleteObjectAct, SIGNAL(triggered()), this, SLOT(deleteObject()));

    duplicateObjectAct = new QAction(QString::fromUtf8("Duplicar objeto"), this);
//    duplicateObjectAct->setShortcuts(QKeySequence(Qt::Key_D));
    duplicateObjectAct->setEnabled(false);
    duplicateObjectAct->setStatusTip(QString::fromUtf8("Duplicar objetos selecionados."));
    connect(duplicateObjectAct, SIGNAL(triggered()), this, SLOT(duplicateObject()));

    analysisObjectAct = new QAction(QString::fromUtf8("Analisar objeto"), this);
    analysisObjectAct->setStatusTip(QString::fromUtf8("Analisar o objeto selecionado"));
    analysisObjectAct->setDisabled(true);
    connect(analysisObjectAct, SIGNAL(triggered()), this, SLOT(analyzeObject()));

    QAction *showAxisAct = new QAction(QString::fromUtf8("Eixos"), this);
    showAxisAct->setCheckable(true);
    showAxisAct->setChecked(true);
//    showAxisAct->setShortcuts();
    showAxisAct->setStatusTip(QString::fromUtf8("Mostrar eixos."));
    connect(showAxisAct, SIGNAL(toggled(bool)), canvas, SLOT(changeShowAxis(bool)));

    QAction *showGridAct = new QAction(QString::fromUtf8("Grade"), this);
    showGridAct->setCheckable(true);
    showGridAct->setChecked(true);
//    showGridAct->setShortcuts();
    showGridAct->setStatusTip(QString::fromUtf8("Mostrar grade."));
    connect(showGridAct, SIGNAL(toggled(bool)), canvas, SLOT(changeShowGrid(bool)));

    QAction *shoNormalAct = new QAction(QString::fromUtf8("Normal"), this);
    shoNormalAct->setCheckable(true);
    shoNormalAct->setChecked(false);
//    showGridAct->setShortcuts();
    shoNormalAct->setStatusTip(QString::fromUtf8("Mostrar normais das faces."));
    connect(shoNormalAct, SIGNAL(toggled(bool)), canvas, SLOT(changeShowNormal(bool)));

	QAction *viewTreePanelAct = treePanelDock->toggleViewAction();
//	QAction *viewPanelAct = ___PanelDock->toggleViewAction();



    //Criando toolbar ----------------------------------------------------------

    QAction *newPolygonAct = new QAction(QIcon("../bitmaps/polygon.xpm"), QString::fromUtf8("Novo polígono"), this);
    newPolygonAct->setStatusTip(QString::fromUtf8("Cria um novo polígono."));
    connect(newPolygonAct, SIGNAL(triggered()), this, SLOT(newPolygonDialog()));

    QAction *newCuboidAct = new QAction(QIcon("../bitmaps/cuboid.xpm"), QString::fromUtf8("Novo cubóide"), this);
    newCuboidAct->setStatusTip(QString::fromUtf8("Cria um novo cubóde."));
    connect(newCuboidAct, SIGNAL(triggered()), this, SLOT(newCuboidDialog()));

    QAction *newSphereAct = new QAction(QIcon("../bitmaps/sphere.xpm"), QString::fromUtf8("Nova esfera"), this);
    newSphereAct->setStatusTip(QString::fromUtf8("Cria uma nova esfera."));
    connect(newSphereAct, SIGNAL(triggered()), this, SLOT(newSphereDialog()));

    QAction *newCylinderAct = new QAction(QIcon("../bitmaps/cylinder.xpm"), QString::fromUtf8("Novo cilindro"), this);
    newCylinderAct->setStatusTip(QString::fromUtf8("Cria um novo cilindro."));
    connect(newCylinderAct, SIGNAL(triggered()), this, SLOT(newCylinderDialog()));

    QAction *newConeAct = new QAction(QIcon("../bitmaps/cone.xpm"), QString::fromUtf8("Novo cone"), this);
    newConeAct->setStatusTip(QString::fromUtf8("Cria um novo cone."));
    connect(newConeAct, SIGNAL(triggered()), this, SLOT(newConeDialog()));

    QToolBar *objectsToolBar = addToolBar(tr("Barra de primitivas"));
    objectsToolBar->addAction(newPolygonAct);
    objectsToolBar->addAction(newCuboidAct);
    objectsToolBar->addAction(newSphereAct);
    objectsToolBar->addAction(newCylinderAct);
    objectsToolBar->addAction(newConeAct);

	QAction *veiwObjectsToolBarAct = objectsToolBar->toggleViewAction();



    newShowFaceAct = new QAction(QIcon("../bitmaps/showFace.xpm"), QString::fromUtf8("Mostar faces"), this);
    newShowFaceAct->setCheckable(true);
    newShowFaceAct->setChecked(true);
    newShowFaceAct->setStatusTip(QString::fromUtf8("Mostra as faces dos objetos."));
    connect(newShowFaceAct, SIGNAL(toggled(bool)), this, SLOT(changeShowFace(bool)));

    newShowEdgeAct = new QAction(QIcon("../bitmaps/showEdge.xpm"), QString::fromUtf8("Mostar arestas"), this);
    newShowEdgeAct->setCheckable(true);
    newShowEdgeAct->setChecked(true);
    newShowEdgeAct->setStatusTip(QString::fromUtf8("Mostra as arestas dos objetos."));
    connect(newShowEdgeAct, SIGNAL(toggled(bool)), this, SLOT(changeShowEdge(bool)));

    newShowVertexAct = new QAction(QIcon("../bitmaps/showVertex.xpm"), QString::fromUtf8("Mostar vértices"), this);
    newShowVertexAct->setCheckable(true);
    newShowVertexAct->setChecked(true);
    newShowVertexAct->setStatusTip(QString::fromUtf8("Mostra os vértices dos objetos."));
    connect(newShowVertexAct, SIGNAL(toggled(bool)), this, SLOT(changeShowVertex(bool)));

    QToolBar *viewToolBar = addToolBar(tr("Barra de visualização"));
    viewToolBar->addAction(newShowFaceAct);
    viewToolBar->addAction(newShowEdgeAct);
    viewToolBar->addAction(newShowVertexAct);

	QAction *veiwViewToolBarAct = viewToolBar->toggleViewAction();




    QAction *translateAct = new QAction(QIcon("../bitmaps/translate.xpm"), QString::fromUtf8("Translação"), this);
    translateAct->setStatusTip(QString::fromUtf8("Translada os objetos selecionados."));
    connect(translateAct, SIGNAL(triggered()), this, SLOT(translateOperation()));

    rotateAct = new QAction(QIcon("../bitmaps/rotate.xpm"), QString::fromUtf8("Rotação"), this);
    rotateAct->setStatusTip(QString::fromUtf8("Rotaciona os objetos selecionados."));
    connect(rotateAct, SIGNAL(triggered()), this, SLOT(rotateOperation()));

    scaleAct = new QAction(QIcon("../bitmaps/scale.xpm"), QString::fromUtf8("Escala"), this);
    scaleAct->setStatusTip(QString::fromUtf8("Escalona os objetos selecionados."));
    connect(scaleAct, SIGNAL(triggered()), this, SLOT(scaleOperation()));

    sweepAct = new QAction(QIcon("../bitmaps/sweep.xpm"), QString::fromUtf8("Sweep"), this);
    sweepAct->setStatusTip(QString::fromUtf8("Faz sweep nas faces selecionadas."));
    connect(sweepAct, SIGNAL(triggered()), this, SLOT(sweepOperation()));

    holeAct = new QAction(QIcon("../bitmaps/hole.xpm"), QString::fromUtf8("Buraco"), this);
    holeAct->setStatusTip(QString::fromUtf8("Faz um buraco entre as duas faces selecionadas."));
    connect(holeAct, SIGNAL(triggered()), this, SLOT(holeOperation()));


    geometricOperationToolBar = addToolBar(QString::fromUtf8("Barra de operações geométricas"));
    geometricOperationToolBar->addAction(translateAct);
    geometricOperationToolBar->addAction(rotateAct);
    geometricOperationToolBar->addAction(scaleAct);
    geometricOperationToolBar->addAction(sweepAct);
    geometricOperationToolBar->addAction(holeAct);
    geometricOperationToolBar->setDisabled(true);


    //Criando menus ------------------------------------------------------------
    QMenu *fileMenu;
    QMenu *editMenu;
    QMenu *viewMenu;

    fileMenu = menuBar()->addMenu(QString::fromUtf8("&Arquivo"));
    fileMenu->addAction(newSceneAct);
    fileMenu->addSeparator();
//    fileMenu->addAction(openSceneAct);
//    fileMenu->addAction(openObjectAct);
    fileMenu->addSeparator();
    fileMenu->addAction(saveObjectsAct);
    fileMenu->addAction(saveObjectsAsAct);
    fileMenu->addSeparator();
    fileMenu->addAction(exitAct);

    editMenu = menuBar()->addMenu(QString::fromUtf8("&Editar"));
    editMenu->addAction(editObjectAct);
    editMenu->addAction(deleteObjectAct);
//    editMenu->addAction(duplicateObjectAct);
    editMenu->addSeparator();

    viewMenu = menuBar()->addMenu(QString::fromUtf8("&Visualizar"));
    viewMenu->addAction(showAxisAct);
    viewMenu->addAction(showGridAct);
    viewMenu->addAction(shoNormalAct);
    viewMenu->addSeparator();
    viewMenu->addAction(viewTreePanelAct);
//    viewMenu->addAction(viewPanelAct);
    viewMenu->addSeparator();
    viewMenu->addAction(veiwObjectsToolBarAct);
    viewMenu->addAction(veiwViewToolBarAct);




    selectAdjacentFaceAct = new QAction(QString::fromUtf8("Faces adjacentes"), this);
    selectAdjacentFaceAct->setStatusTip(QString::fromUtf8("Selecionar as faces adijacentes"));
    selectAdjacentFaceAct->setDisabled(true);
    connect(selectAdjacentFaceAct, SIGNAL(triggered()), this, SLOT(selectAdjacentFace()));

    selectAdjacentEdgeAct = new QAction(QString::fromUtf8("Arestas adjacentes"), this);
    selectAdjacentEdgeAct->setStatusTip(QString::fromUtf8("Selecionar as arestas adijacentes"));
    selectAdjacentEdgeAct->setDisabled(true);
    connect(selectAdjacentEdgeAct, SIGNAL(triggered()), this, SLOT(selectAdjacentEdge()));

    selectAdjacentVertexAct = new QAction(QString::fromUtf8("Vértices adjacentes"), this);
    selectAdjacentVertexAct->setStatusTip(QString::fromUtf8("Selecionar os vértices adijacentes"));
    selectAdjacentVertexAct->setDisabled(true);
    connect(selectAdjacentVertexAct, SIGNAL(triggered()), this, SLOT(selectAdjacentVertex()));



    tree->addAction(analysisObjectAct);
    tree->addAction(deleteObjectAct);
//    tree->addAction(duplicateObjectAct);
    tree->addAction(selectAdjacentFaceAct);
    tree->addAction(selectAdjacentEdgeAct);
    tree->addAction(selectAdjacentVertexAct);
}

void Window::updateActions(){
//    QTreeWidgetItem *rootItem = tree->invisibleRootItem();
    bool enable = (previousSelected.size() > 0);

//    saveSceneAct->setEnabled(enable);
//    saveObjectAct->setEnabled(enable);
//    duplicateObjectAct->setEnabled(enable);
    geometricOperationToolBar->setEnabled(enable);

    holeAct->setEnabled(false);
    sweepAct->setEnabled(false);
    if(enable)
    {
        QTreeWidgetItem *item = previousSelected.front();
        unsigned int type = ((TreeItem *)item)->getType();
        bool restrictedEnable = (type != DEFAULT) && (type != OBJECT);
        selectAdjacentFaceAct->setEnabled(restrictedEnable);
        selectAdjacentEdgeAct->setEnabled(restrictedEnable);
        selectAdjacentVertexAct->setEnabled(restrictedEnable);

        restrictedEnable = (type == OBJECT);
        deleteObjectAct->setEnabled(restrictedEnable);
        duplicateObjectAct->setEnabled(restrictedEnable);

        if(type == FACE){
            sweepAct->setEnabled(true);
            if(previousSelected.size() == 2) holeAct->setEnabled(true);
        }else{
            if(type == DEFAULT)
                if( ((TreeItem *)item->child(0))->getType() == FACE )
                    sweepAct->setEnabled(true);
        }
    }else
    {
        selectAdjacentFaceAct->setEnabled(false);
        selectAdjacentEdgeAct->setEnabled(false);
        selectAdjacentVertexAct->setEnabled(false);

        deleteObjectAct->setEnabled(false);
        duplicateObjectAct->setEnabled(false);
    }

    saveObjectsAct->setEnabled(true);

    analysisObjectAct->setDisabled(true);
    if(previousSelected.size() == 1)
        if(((TreeItem *)previousSelected.front())->getType() == OBJECT)
            analysisObjectAct->setEnabled(true);

    canvas->updateGL();
}

//void Window::updateAllTree(){
//    QTreeWidgetItem *rootItem = tree->invisibleRootItem();
//
//    ObjectTreeItem *objectTreeItem;
//    for(int i = 0; i < rootItem->childCount(); i++){
//        objectTreeItem = (ObjectTreeItem *) rootItem->child(i);
//        objectTreeItem->updateObject();
//    }
//}
//
//void Window::selectTreeItem(QTreeWidgetItem *, int){
////    ((TreeItem *)_item)->select();
//    canvas->updateGL();
//}

//void Window::selectObject(Object *_o){
//    canvas->getScene()->selectObject(_o);
//}

void Window::newScene(){
    std::cout <<"Perguntar se não quer gravar" <<std::endl;
    tree->clear();
    canvas->newScene();
    output.setFile(NULL);
}

int Window::addTreeItem(Object *_obj, QTreeWidgetItem *_item, bool _setId){
    if(_setId){
        _obj->setId(canvas->getScene()->nextObjectsID());
    }

//    QTreeWidgetItem *newItem =
    new ObjectTreeItem(_item, _obj);

    return _obj->getId();
}

int Window::updateObjects(std::vector<Object *> _objs){
    inOperation = true;
    QTreeWidgetItem *rootItem = tree->invisibleRootItem();

    bool setId = (canvas->getScene()->getObjectsSize() > 0);

    int currentMaxId, maxId = -1;
    for(unsigned int i = 0; i < _objs.size(); i++){
        Object *obj = _objs.at(i);
        canvas->getScene()->addObject(obj);

        currentMaxId = addTreeItem(obj, rootItem, setId);
        if(currentMaxId > maxId) maxId = currentMaxId;
    }

    inOperation = false;
    return maxId;
}

void Window::openObjects(){
    QString filename = QFileDialog::getOpenFileName(this, tr("Acrescentar objetos"), QDir::currentPath(),tr("Arquivo objetos em half-edge (*.heo)"));

    if (!filename.isNull()){
//        qDebug() << "abrindo: " << filename;
        QFile* file = new QFile(filename);

        Input input;
        int maxId = updateObjects(input.parseObjects(file));
        canvas->getScene()->setNextObjectsID(maxId);

        output.setFile(file);
	}
	updateActions();
//	updateTreesVolume(false);
}

void Window::openSceneObjects(){

    std::cout <<"Podia perguntar se a pessoa quer salvar o ultimo ou não" <<std::endl;

	QString filename = QFileDialog::getOpenFileName(this, tr("Abrir cena"), QDir::currentPath(),tr("Arquivo de cenas (*.ohe)"));

    if (!filename.isNull()){
        newScene();
        qDebug() << "abrindo: " << filename;
        QFile* file = new QFile(filename);

        Input input;
        int maxId = updateObjects(input.parseObjects(file));
        canvas->getScene()->setNextObjectsID(maxId);

        output.setFile(file);
	}
	updateActions();
}

void Window::saveSceneObjects(){
    if(output.isFileNull())
        if(!saveSceneObjectsAs()) return;

    output.parseObjects(canvas->getScene());

    saveObjectsAct->setEnabled(false);
}

bool Window::saveSceneObjectsAs(){
	QString filename = QFileDialog::getSaveFileName(this, tr("Salvar objetos da cena como..."), QDir::currentPath(), tr("Objetos em half-edge (*.heo)"));

    if (filename.isNull()) return false;

    if (QFileInfo(filename).suffix().isEmpty())
        filename += ".heo";

    QFile* file = new QFile(filename);

	output.parseObjects(file, canvas->getScene());

    saveObjectsAct->setEnabled(false);

    return true;
}

void Window::editObjectDialog(QTreeWidgetItem * _item, int){
    _item->setSelected(false);
    inOperation = true;

//    Object *obj = ((ObjectTreeItem *)_item)->getObject();

    ObjectDialog *dlg = new ObjectDialog((TreeItem *)_item, this);
    dlg->show();
    connect(dlg, SIGNAL(done()), canvas, SLOT(updateGL()));

    updateActions();

    inOperation = false;
}

void Window::deleteObject(){
    inOperation = true;
    TreeItem *treeItem;

    for(int i = previousSelected.size(); i > 0 ; i--)
    {
        treeItem = (TreeItem *)previousSelected[i-1];

        if(treeItem->getType() == OBJECT)
        {
            Object *obj = ((ObjectTreeItem *)treeItem)->getObject();
            canvas->getScene()->deleteObject(obj);
            previousSelected.erase(previousSelected.begin() + i-1);
            delete treeItem;
        }
    }

    inOperation = false;
    updateActions();
}

void Window::duplicateObject(){
    inOperation = true;
    TreeItem *treeItem;

    for(int i = 0; i < previousSelected.size() ; i++)
    {
        treeItem = (TreeItem *)previousSelected[i];

        if(treeItem->getType() == OBJECT)
        {
            Object *obj = ((ObjectTreeItem *)treeItem)->getObject();
            Object *newObj = new Object(canvas->getScene()->nextObjectsID(), obj);

            addPrimitive(newObj, COPY);
        }
    }

    inOperation = false;
    updateActions();
}

void Window::analyzeObject(){
    if(previousSelected.size() != 1) std::cout <<"Analisando numero de objetos errado" <<std::endl;

    TreeItem *item = (TreeItem *)previousSelected.front();
    if (item->getType() != OBJECT) std::cout <<"Analisando algo que não é objeto" <<std::endl;;

    Object *obj = ((ObjectTreeItem *)item)->getObject();

    AnalysisDialog *dlg = new AnalysisDialog(obj, this);
    dlg->show();
}

void Window::changeSelection(){

//    std::cout <<"------Estaria mudando! seleção!" <<std::endl;
    if(inOperation) return;

//    std::cout <<"\t\tAntes de mudar!" <<std::endl;

    //testando pais
    QList<QTreeWidgetItem *> selected = tree->selectedItems();
    if(selected.empty())
    {
        //descelecionando os anteriores
        for(int i = 0; i < previousSelected.size(); i++){
            QTreeWidgetItem *item = previousSelected.at(i);
            ((TreeItem *)item)->select(false);
        }
        previousSelected.clear();

        updateActions();
        canvas->updateGL();
        return;
    }

    QTreeWidgetItem *parentTop = selected.at(0)->parent();
    //guarda o pai do primeiro objeto
    if(parentTop)
    {
        //se o pai foi m objeto
        //isto é, é o filho que guarda todas as faces, todos as arestas ou todos os vertices
        //desceleciona qualquer outra coisa e sai
        if( ((TreeItem *)parentTop)->getType() == OBJECT )
        {
            inOperation = true;
            //descelecionando os anteriores
            for(int i = 0; i < previousSelected.size(); i++){
                QTreeWidgetItem *item = previousSelected.at(i);
                ((TreeItem *)item)->select(false);
            }
            previousSelected.clear();

            //selecionando o primeiro
            QTreeWidgetItem *item = selected.at(0);
            ((TreeItem *)item)->select(true);
            previousSelected.push_back(item);

            //tirando a seleção da arvore do resto
            for(int i = 1; i < selected.size(); i++){
                QTreeWidgetItem *item = selected.at(i);
                item->setSelected(false);

            }

            updateActions();
            canvas->updateGL();
            rotateAct->setDisabled(true);
            scaleAct->setDisabled(true);
            inOperation = false;
            return;
        }

    }


    inOperation = true;
    for(int i = selected.size(); i > 1 ; i--){
        QTreeWidgetItem *item = selected.at(i - 1);
        QTreeWidgetItem *parentItem = item->parent();

        if(parentTop != parentItem)
        {
            item->setSelected(false);
            selected.erase(selected.begin() + i - 1);
        }

    }
    inOperation = false;

    //descelecionando os anteriores
    for(int i = 0; i < previousSelected.size(); i++){
        QTreeWidgetItem *item = previousSelected.at(i);
        ((TreeItem *)item)->select(false);
    }
    previousSelected.clear();

    //selecionando de fato os novos
    for(int i = 0; i < selected.size(); i++){
        QTreeWidgetItem *item = selected.at(i);
        ((TreeItem *)item)->select(true);
        previousSelected.push_back(item);
    }

    rotateAct->setEnabled(((TreeItem *)previousSelected.front())->getType() == OBJECT);
    scaleAct->setEnabled(((TreeItem *)previousSelected.front())->getType() == OBJECT);

    updateActions();

//    std::cout <<"\t\tMudou!" <<std::endl;
    canvas->updateGL();

}

void Window::addPrimitive(Object *_obj, unsigned int _type){
    inOperation = true;
    QTreeWidgetItem *rootItem = tree->invisibleRootItem();

    canvas->getScene()->addObject(_obj);
    /*QTreeWidgetItem *newCuboidItem = */new ObjectTreeItem(rootItem, _obj, _type);

    updateActions();

    inOperation = false;
    canvas->updateGL();
}

void Window::newPolygonDialog(){
    PolygonDialog *dlg = new PolygonDialog(canvas->getScene()->nextObjectsID(), this);
    dlg->show();

    connect(dlg, SIGNAL(done(Object *, unsigned int)), this, SLOT(addPrimitive(Object *, unsigned int)));
}

void Window::newCuboidDialog(){
    CuboidDialog *dlg = new CuboidDialog(canvas->getScene()->nextObjectsID(), this);
    dlg->show();

    connect(dlg, SIGNAL(done(Object *, unsigned int)), this, SLOT(addPrimitive(Object *, unsigned int)));
}

void Window::newSphereDialog(){
    SphereDialog *dlg = new SphereDialog(canvas->getScene()->nextObjectsID(), this);
    dlg->show();

    connect(dlg, SIGNAL(done(Object *, unsigned int)), this, SLOT(addPrimitive(Object *, unsigned int)));
}

void Window::newCylinderDialog(){
    CylinderDialog *dlg = new CylinderDialog(canvas->getScene()->nextObjectsID(), this);
    dlg->show();

    connect(dlg, SIGNAL(done(Object *, unsigned int)), this, SLOT(addPrimitive(Object *, unsigned int)));
}

void Window::newConeDialog(){
    ConeDialog *dlg = new ConeDialog(canvas->getScene()->nextObjectsID(), this);
    dlg->show();

    connect(dlg, SIGNAL(done(Object *, unsigned int)), this, SLOT(addPrimitive(Object *, unsigned int)));
}
